package com.hopsof.tools.uimanagerdefaultslookup;

import java.awt.BorderLayout;
import java.awt.CardLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Font;
import java.awt.GridLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.util.Collections;
import java.util.Comparator;
import java.util.Enumeration;
import java.util.Vector;

import javax.imageio.ImageIO;
import javax.swing.BorderFactory;
import javax.swing.Icon;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextField;
import javax.swing.JTree;
import javax.swing.LookAndFeel;
import javax.swing.SwingConstants;
import javax.swing.UIDefaults;
import javax.swing.UIManager;
import javax.swing.border.Border;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import javax.swing.event.TreeSelectionEvent;
import javax.swing.event.TreeSelectionListener;
import javax.swing.plaf.ComponentUI;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.TreePath;

/**
 *        Licensed to the Apache Software Foundation (ASF) under one
 *      or more contributor license agreements.  See the NOTICE file
 *      distributed with this work for additional information
 *      regarding copyright ownership.  The ASF licenses this file
 *      to you under the Apache License, Version 2.0 (the
 *      "License"); you may not use this file except in compliance
 *      with the License.  You may obtain a copy of the License at
 *
 *        http://www.apache.org/licenses/LICENSE-2.0
 *
 *      Unless required by applicable law or agreed to in writing,
 *      software distributed under the License is distributed on an
 *      "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 *      KIND, either express or implied.  See the License for the
 *      specific language governing permissions and limitations
 *      under the License.
 *      
 *      Copyright 2012 Hopsof
 *      
 * @author Brandon Murphy
 * @see <a href="http://www.hopsof.com/">http://www.hopsof.com/</a> 
 *
 */

//TODO: Look and Feel selector
//TODO: Icon Preview
public class UIManagerDefaultsLookup 
{
	public static JPanel cardPanel = null;
	
	public static class MyComparator implements Comparator<String> 
	{
		public int compare(String strA, String strB) 
		{
			return strA.compareToIgnoreCase(strB);
		}
	}
	
	public static String getCodeFieldText(String key)
	{
		String prefix = "UIManager.get";
		String type   = "";
		String open   = "(\"";
		String close  = "\");";
				
		Object object = UIManager.get(key);
		
		if(object instanceof Boolean)
		{
			type = "Boolean";
		}
		else if(object instanceof Border)
		{
			type = "Border";
		}
		else if(object instanceof Color)
		{
			type = "Color";
		}
		else if(object instanceof Dimension)
		{
			type = "Dimension";
		}
		else if(object instanceof Font)
		{
			type = "Font";
		}
		else if(object instanceof Icon)
		{
			type = "Icon";
		}
		else if(object instanceof Insets)
		{
			type = "Insets";
		}
		else if(object instanceof Integer)
		{
			type = "Int";
		}
		else if(object instanceof LookAndFeel)
		{
			type = "LookAndFeel";
		}
		else if(object instanceof UIDefaults)
		{
			type = "Defaults";
		}
		else if(object instanceof String)
		{
			type = "String";
		}
		else if(object instanceof ComponentUI)
		{
			type = "UI";
		}
		
		return prefix + type + open + key + close;
	}
	
	public static class TreeAdapter implements TreeSelectionListener, ListSelectionListener
	{
		public TreeAdapter(JTextField keyField, JTextField valueField, JTextField codeField, JLabel colorLabel)
		{
			_keyField	= keyField;
			_valueField	= valueField;
			_codeField	= codeField;
			_colorLabel = colorLabel;
		}

		@Override
		public void valueChanged(TreeSelectionEvent e) 
		{
			Object[] path = e.getPath().getPath();
			
			StringBuffer temp = new StringBuffer();
			
			
			for(int i=1; i<path.length-1; i++)
			{
				temp.append(path[i] + ".");
			}
			
			temp.append(path[path.length-1]);
			
			_keyField.setText(temp.toString());
			_codeField.setText(getCodeFieldText(temp.toString()));
			
			if(UIManager.get(temp.toString()) == null)
			{
				_keyField.setText("");
				_codeField.setText("");
				_colorLabel.setBackground(null);
				_colorLabel.setOpaque(false);
			}
			else 
			{
				if(UIManager.get(temp.toString()) instanceof Color)
				{
					_colorLabel.setOpaque(true);
					_colorLabel.setBackground(UIManager.getColor(temp.toString()));
				}
				else
				{
					_colorLabel.setBackground(null);
					_colorLabel.setOpaque(false);
				}
			}

			
			try
			{
				_valueField.setText(UIManager.get(temp.toString()).toString());
			}
			catch(Exception exception)
			{
				_valueField.setText("");
			}
			
		}
		


		@Override
		public void valueChanged(ListSelectionEvent e) {
			
			JList list = ((JList)e.getSource());
			
			String temp = list.getModel().getElementAt(list.getSelectedIndex()).toString();
			
			_keyField.setText(temp.toString());
			_codeField.setText(getCodeFieldText(temp.toString()));
			
			if(UIManager.get(temp.toString()) == null)
			{
				_keyField.setText("");
				_codeField.setText("");
				_colorLabel.setBackground(null);
				_colorLabel.setOpaque(false);
			}
			else 
			{
				if(UIManager.get(temp.toString()) instanceof Color)
				{
					_colorLabel.setOpaque(true);
					_colorLabel.setBackground(UIManager.getColor(temp.toString()));
				}
				else
				{
					_colorLabel.setBackground(null);
					_colorLabel.setOpaque(false);
				}
			}
			
			if(UIManager.get(temp.toString()) == null)
			{
				_keyField.setText("");
				_codeField.setText("");
			}
			
			try
			{
				_valueField.setText(UIManager.get(temp).toString());
			}
			catch(Exception exception)
			{
				_valueField.setText("");
			}
			
		}
		
		JTextField _keyField, _valueField, _codeField;
		JLabel _colorLabel;
		
	}
	
	public static void main(String args[])
	{
		final JFrame frame = new JFrame();
		
		DefaultMutableTreeNode topNode = new DefaultMutableTreeNode();
		
		
		UIDefaults uiDefaults = UIManager.getDefaults();
		Enumeration<?> enumeration = uiDefaults.keys();
		
		Vector<String> keys = new Vector<String>();
		
		while(enumeration.hasMoreElements())
		{
			keys.add(enumeration.nextElement().toString());
		}
		
	
		Collections.sort(keys, new MyComparator());
		

		
		for(int i=0; i<keys.size(); i++)
		{			
			
			
			int found = -1;
			String temp = keys.elementAt(i).toString();
			
			String[] tempArray = temp.split("\\.");
			
			DefaultMutableTreeNode currentNode = new DefaultMutableTreeNode();

			currentNode.setUserObject(tempArray[0]);
			
			for(int k=0; k<topNode.getChildCount(); k++)
			{
				if(topNode.getChildAt(k).toString().equals(currentNode.toString()))
				{
					found = k;
				}
			}
			
			if(found == -1)
			{
				topNode.add(currentNode);
			}
			else
			{
				currentNode = (DefaultMutableTreeNode) topNode.getChildAt(found);
			}
			
			
			for(int j=1; j<tempArray.length; j++)
			{
				found = -1;
				DefaultMutableTreeNode newNode = new DefaultMutableTreeNode(tempArray[j]);
				
				for(int k=0; k<currentNode.getChildCount(); k++)
				{
					if(currentNode.getChildAt(k).toString().equals(newNode.toString()))
					{
						found = k;
					}
				}
				
				if(found == -1)
				{
					currentNode.add(newNode);
					currentNode = newNode;	
				}
				else
				{
					currentNode = (DefaultMutableTreeNode) currentNode.getChildAt(found);
				}
			}
		}
		
		JPanel card1 = new JPanel();
		JPanel card2 = new JPanel();
		
		cardPanel = new JPanel(new CardLayout());
		
		cardPanel.add(card1, "Tree View");
		cardPanel.add(card2, "List View");
		
		card1.setLayout(new BorderLayout());
		card2.setLayout(new BorderLayout());
		
		
		
		final JTree jTree = new JTree(topNode);
		final JList jList = new JList(keys);
		
		jTree.setOpaque(true);
		jList.setOpaque(true);
		jTree.setBackground(Color.WHITE);
		jList.setBackground(Color.WHITE);
		
		jTree.setShowsRootHandles(true);
		
		jTree.setRootVisible(false);
		
		JScrollPane treePane = new JScrollPane(jTree);
		JScrollPane listPane = new JScrollPane(jList);
		
		card1.add(treePane, BorderLayout.CENTER);
		card2.add(listPane, BorderLayout.CENTER);
		
		JPanel panel 		= new JPanel();
		JPanel panelLeft 	= new JPanel();
		JPanel panelCenter 	= new JPanel();
		
		JLabel colorLabel = new JLabel("Color Preview");
		
		colorLabel.setHorizontalAlignment(SwingConstants.CENTER);
		colorLabel.setPreferredSize(new Dimension(100, 100));
		colorLabel.setBorder(BorderFactory.createLineBorder(Color.BLACK, 2));
		
		
		panel.setLayout(new BorderLayout());
		panelLeft.setLayout(new GridLayout(0, 1));
		panelCenter.setLayout(new GridLayout(0, 1));
		
		JLabel		keyLabel 	= new JLabel("Full Key Name: ");
		JTextField 	keyField 	= new JTextField();
		
		JLabel		valueLabel 	= new JLabel("Default Value: ");
		JTextField 	valueField 	= new JTextField();
		
		JLabel		codeLabel 	= new JLabel("Copyable Code: ");
		JTextField 	codeField 	= new JTextField();
		
		JButton button = new JButton("Switch Views");
		JButton aboutButton = new JButton("About");
		JButton closeButton = new JButton("Close");
		
		closeButton.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				System.exit(0);
			}
		});
		
		aboutButton.addActionListener(new ActionListener(){
			public void actionPerformed(ActionEvent e) {
				AboutBox aboutBox = new AboutBox(frame);
				aboutBox.setVisible(true);
			}});
		
		button.addActionListener(new ActionListener(){
			public void actionPerformed(ActionEvent e) {
				((CardLayout)UIManagerDefaultsLookup.cardPanel.getLayout()).next(UIManagerDefaultsLookup.cardPanel);
				
			}});
		
		panelLeft.add(keyLabel);
		panelCenter.add(keyField);
		panelLeft.add(valueLabel);
		panelCenter.add(valueField);
		panelLeft.add(codeLabel);
		panelCenter.add(codeField);
		
		panelLeft.add(new JLabel("Find: "));
		
		JPanel controlPanel = new JPanel(new FlowLayout(FlowLayout.RIGHT));
		
		controlPanel.add(button);
		controlPanel.add(aboutButton);
		controlPanel.add(closeButton);
		
		JPanel findPanel = new JPanel(new FlowLayout(FlowLayout.LEFT));
		JButton findButton = new JButton("Find Next");
		final JTextField findText = new JTextField();
		findPanel.add(findText);
		findPanel.add(findButton);
		
		
		final ActionListener listener = new ActionListener(){
			public void actionPerformed(ActionEvent e) {
				boolean found = false;
				String text = findText.getText();
				int index = jList.getSelectedIndex() + 1;
				
				if(index >= jList.getModel().getSize() - 1 || index < 0)
				{
					index = 0;
				}
				
				for(int i=index; i<jList.getModel().getSize() && found == false; i++)
				{
					index = i;
					
					if(((String)jList.getModel().getElementAt(i)).toLowerCase().contains(text.toLowerCase()))
					{
						found = true;
					}
				}
				
				if(found == false)
				{
					index = 0;
					
					for(int i=index; i<jList.getModel().getSize() && found == false; i++)
					{
						index = i;
						
						if(((String)jList.getModel().getElementAt(i)).toLowerCase().contains(text.toLowerCase()))
						{
							found = true;
						}
					}
				}
				
				jList.setSelectedIndex(index);
				jList.ensureIndexIsVisible(index);
				
				if(jTree.getSelectionModel().getLeadSelectionRow() < 0)
				{
					jTree.setSelectionInterval(0, 0);
				}
				
				found = false;
				for(int i=0; i<jTree.getRowCount(); i++)
				{
					jTree.expandRow(i);
				}
				
				int[] rows = jTree.getSelectionRows();
				
				if(rows.length < 0)
				{
					index = 0;
				}
				else
				{
					index = rows[0] + 1;
				}
				
				if(index >= jTree.getRowCount())
				{
					index = 0;
				}
				
				for(int i=index; i<jTree.getRowCount() && found == false; i++)
				{
					index = i;
					
					TreePath path = jTree.getPathForRow(index);
					String data = path.getPathComponent(path.getPathCount() - 1).toString();

					if(data.toLowerCase().contains(text.toLowerCase()))
					{
						found = true;
					}
				}
				
				if(found == false)
				{
					index = 0;
					
					for(int i=index; i<jTree.getRowCount() && found == false; i++)
					{
						index = i;
						
						TreePath path = jTree.getPathForRow(index);
						String data = path.getPathComponent(path.getPathCount() - 1).toString();

						if(data.toLowerCase().contains(text.toLowerCase()))
						{
							found = true;
						}
					}
				}
			
				jTree.setSelectionRow(index);
				jTree.scrollRowToVisible(index);
				
			}};
		
			findText.addKeyListener(new KeyListener(){
				public void keyPressed(KeyEvent arg0) {
			
					
				}

				public void keyReleased(KeyEvent arg0) {
		
					
				}

				public void keyTyped(KeyEvent e) {
					if(e.getKeyChar() == '\n')
					{
						listener.actionPerformed(new ActionEvent(e, 0, null));
					}
					
				}});
		
		findButton.addActionListener(listener);
		
		
		findText.setPreferredSize(new Dimension(150, (int) findText.getPreferredSize().getHeight()));
		findButton.setPreferredSize(new Dimension((int) findButton.getPreferredSize().getWidth(), (int) findText.getPreferredSize().getHeight()));
		
		
		JPanel bottomPanel = new JPanel(new GridLayout(1, 0));
		bottomPanel.add(findPanel);
		bottomPanel.add(controlPanel);
		
		panelCenter.add(bottomPanel);
		
		panel.add(panelLeft, BorderLayout.WEST);
		panel.add(panelCenter, BorderLayout.CENTER);
		panel.add(colorLabel, BorderLayout.EAST);
		
		jTree.addTreeSelectionListener(new TreeAdapter(keyField, valueField, codeField, colorLabel));
		jList.addListSelectionListener(new TreeAdapter(keyField, valueField, codeField, colorLabel));
		
		
		ImageIcon image = null;
    	URL url = AboutBox.class.getClassLoader().getResource("com/hopsof/tools/uimanagerdefaultslookup/glass.png");
    	
    	if(url == null)
    	{
    		try {
				image = new ImageIcon(ImageIO.read(new File("bin/com/hopsof/tools/uimanagerdefaultslookup/glass.png")));
			} catch (IOException e1) {
				e1.printStackTrace();
			}
    	}
    	else
    	{
    		image = new ImageIcon(url);
    	}
		
		frame.setIconImage(image.getImage());
		
		frame.setTitle("UIManagerDefaultsLookup");
		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		frame.setLayout(new BorderLayout());
		frame.add(cardPanel, BorderLayout.CENTER);
		frame.add(panel, BorderLayout.SOUTH);
		frame.setLocationByPlatform(true);
		frame.setVisible(true);
		frame.setSize(800, 600);

	}
}
